Proc mi nezafunguje try->finally v threadu?

Otázka od: Martin Krim

1. 10. 2004 17:24



> > Muzete mi, prosim, nekdo rict, proc... kdyz mam nejakou botu v procedure
> Proved se mi nezobrazi zadne chyba (vetsinou aplikace jen tise zamrzne) a
> kdyz nezamrzne, tak cely ten thread nejakym zpusobem zhavaruje a neprovede
> se ani ta cast toho finally.

IMHO, kazde vlakno ma svuj vlastni zasobnik a vyjimky se vzdy siri po
zasobniku, tedy volanim metody Synchronize presmerujete vykonani metody
Proved do hlavniho vlakna programu, tedy k vyvolani vyjimky by melo dojit v
hlavnim vlakne programu a za pokus by stalo zkusit implementovat obsluhu
udalosti TApplication.OnException a pokusit se tak zachytit vyjimku - BTW,
pomoci teto udalosti muzete zachytavat vsechny neosetrene vyjimky (z
hlavniho vlakna programu) a vypsat uzivateli neco jako
"Omlouvame se za
zpusobene potize......".

Martin Krim



Odpovedá: Slavomir Skopalik

1. 10. 2004 9:50

Ta konstrukce je ponekud divna.
Jaky mela mit ucel ?
Zkus si dat break point do sekce finally, mel to normalne funguje.
Jestli vznikne vyjimka v threadu, tak ten se ukonci (vyjimkou jsou
windows W9x, kde padne cela aplikace do BSOD).
Takze doporucuji misto finally pouzit except, a dobre promyslet
ten suspend (ze by preklep ?).

 Slavek

> procedure TMainThread.Execute;
> begin
> while not Terminated do
> try
> Synchronize(proved);
> finally
> if not Terminated then Suspend;
> end;//try->finally
> end;
>
> Muzete mi, prosim, nekdo rict, proc... kdyz mam nejakou botu
> v procedure Proved se mi nezobrazi zadne chyba (vetsinou
> aplikace jen tise zamrzne) a kdyz nezamrzne, tak cely ten
> thread nejakym zpusobem zhavaruje a neprovede se ani ta cast
> toho finally. PROC? Diky Jirka


Odpovedá: Ing. Jiri Sokol

1. 10. 2004 15:00

> Od: Slavomir Skopalik <skopalik@elektlabs.cz>
> Datum: 01.10.2004 11:16:56
>
> Ta konstrukce je ponekud divna.
> Jaky mela mit ucel ?
> Zkus si dat break point do sekce finally, mel to normalne funguje.
> Jestli vznikne vyjimka v threadu, tak ten se ukonci (vyjimkou jsou
> windows W9x, kde padne cela aplikace do BSOD).
> Takze doporucuji misto finally pouzit except, a dobre promyslet
> ten suspend (ze by preklep ?).
>
> Slavek

V tom threadu mam kod, ktery se v urcitych intervalech, po slpneni urcitych
podminek opakuje - ridi hlavni thread aplikace volanim Resume threadu. Jakmile
ta urcita cast kodu skonci, ma se thread "uspat" a cekat na dalsi pozadavek
spusteni.
Ze se mi to chova nekorektne jsem zjistil napr tim, ze jsem mel preklep v kodu,
ktery mi prekladac nenasel a sice:

Vlakno:=TThread(nil); //tady mi vypadlo ".Create"
Vlakno.Params.Clear; //<-- tady se to kousne beze slova... aplikace se tvari,
ze v pohode bezi...  

atd. Pak se mi nekde stane, ze mi nejaka cast kodu toho "Proved" zhuci na
vyjimku - bohuzel "zatim" nepisu kod bez chyb. Proto jsem to dal do toho bloku
try->finally a doufal, ze kdyz mi to v tom kodu zhuci, dostane se to do bloku
finally a aplikace zahlasi chybu, ke ktere doslo, a bude dal pokracovat...

bohuzel se tak nedeje. V kodu pouzivam komponenty TIBDatabase, TIBTransaction,
TIBDataset, TIBQuery - nekde jsem vycetl, ze IB/FB neni tzv. "thread safety" a
tak si vsechny spojeni na databazi vytvarim v tele Create toho threadu. Doufam,
ze to s tim nesouvisi...

Diky za dalsi pomoc
Jirka

Odpovedá: Ing. Jiri Sokol

1. 10. 2004 15:20

> Od: Ing. Jiri Sokol <js-delphi@email.cz>
> Datum: 01.10.2004 15:23:43
>
> > Od: Slavomir Skopalik <skopalik@elektlabs.cz>
> > Datum: 01.10.2004 11:16:56
> >
> > Ta konstrukce je ponekud divna.
> > Jaky mela mit ucel ?
> > Zkus si dat break point do sekce finally, mel to normalne funguje.
> > Jestli vznikne vyjimka v threadu, tak ten se ukonci (vyjimkou jsou
> > windows W9x, kde padne cela aplikace do BSOD).
> > Takze doporucuji misto finally pouzit except, a dobre promyslet
> > ten suspend (ze by preklep ?).
> >
> > Slavek
>
Omlouvam se, ale v mem predchozim prispevku jsem udelal chybu... -> Posilam
opraveny text. Dekuju za pochopeni.

V tom threadu mam kod, ktery se v urcitych intervalech, po slpneni urcitych
podminek opakuje - ridi hlavni thread aplikace volanim Resume threadu. Jakmile
ta urcita cast kodu skonci, ma se thread "uspat" a cekat na dalsi pozadavek
spusteni.
Ze se mi to chova nekorektne jsem zjistil napr tim, ze jsem mel preklep v kodu,
ktery mi prekladac nenasel a sice:
 
!!!! CHYBA v minulem mailu, omlouvam se... (*> Vlakno:=TThread(nil); //tady mi
vypadlo ".Create" *)

melo byt:

  VlaknoTran:=TIBTransaction(nil); //tady mi vypadlo ".Create"
  VlaknoTran.Params.Clear; //<-- tady se to kousne beze slova... aplikace se
tvari, ze v pohode bezi...  

pricemz VlaknoTran je interni promenna toho threadu.
 
atd. Pak se mi nekde stane, ze mi nejaka cast kodu toho "Proved" zhuci na
vyjimku - bohuzel "zatim" nepisu kod bez chyb. Proto jsem to dal do toho bloku
try->finally a doufal, ze kdyz mi to v tom kodu zhuci, dostane se to do bloku
finally a aplikace zahlasi chybu, ke ktere doslo, a bude dal pokracovat...
Nicmene i na podle me primitivnim prikladu, ktery se snad (bez urazky) muzu
stat komukoliv, do bloku finally nedojde... PROC????
 
bohuzel se tak nedeje. V kodu pouzivam komponenty TIBDatabase, TIBTransaction,
TIBDataset, TIBQuery - nekde jsem vycetl, ze IB/FB neni tzv. "thread safety" a
tak si vsechny spojeni na databazi vytvarim v tele Create toho threadu. Doufam,
ze to s tim nesouvisi...
 
Diky za dalsi pomoc a omlouvam se za predchozi mystifikaci
Jirka

Odpovedá: Petr Vones

1. 10. 2004 17:04

From: "Ing. Jiri Sokol" <js-delphi@email.cz>
> Ahoj, mam asi trivialni dotaz, ale nevim si s nim rady.
> Ma cca takovou konstrukci
> procedure TMainThread.Execute;
> begin
> while not Terminated do
> try
> Synchronize(proved);
> finally
> if not Terminated then Suspend;
> end;//try->finally
> end;

To je dost nestastna konstrukce. Takove veci je vhodnejsi resit nejakym
eventem na ktery cekas a nevolat Suspend.

Petr Vones


Odpovedá: Petr Fejfar

1. 10. 2004 17:35

Ing. Jiri Sokol wrote:

> Mam cca takovou konstrukci

> procedure TMainThread.Execute;
> begin
> while not Terminated do
> try
> Synchronize(proved);
> finally
> if not Terminated then Suspend;
> end;//try->finally
> end;

Cert vi, co se ti tam vlastne deje <g>

Jestli totiz mas takovouhle konstrukci, tak se zamysli na tim,
proc vubec vytvaris thread, protoze pokud spoustis
ten vypocet pres synchronize, tak se metoda "proved" vykona v kontextu
*hlavniho* threadu a tvuj TMainThread bude cekat na jeho dokonceni !!!

Cili to bude horsi, nez kdybys to zavolal rovnou z hlavniho threadu  

***

To synchronize pracuje v principu takto:

* V kontextu podruzneho threadu volani Synchronize() zaradi "proved" do
fronty
    spolu s event pro indikaci konce vypoctu a zavola WakeMainThread(),
    coz typicky zpusobi postnuti zpravy WM_NULL instanci TApplication.

* Pak podruzny thread ceka na stav signaled te predane event
    tj. na konec vypoctu

* Po prijmu zpravy WM_NULL v kontextu *hlavniho* threadu instance
TApplication
 pres volani CheckSynchronize() vyzvedne "proved" z fronty a spusti ho

* Az "proved" skonci, tak se signalizuje konec vypoctu pres event, coz
vzbudi
    podruzny thread a ten pokracuje dal.

***

BTW, to je taky odpoved na to, proc treba v prikladu, na ktery te odkazoval
TOndrej nekdy pred mesicem, se synchronize nepouziva: chces-li totiz mit
slusny multiprocessing, musis zapomenout na "siditka" jako synchronize
a navrhnout si vlastni plnohodnotny IPC.


HTH, pf


Odpovedá: Petr Vones

1. 10. 2004 16:56

From: "Ing. Jiri Sokol" <js-delphi@email.cz>
> Jakmile ta urcita cast kodu skonci, ma se thread "uspat" a cekat na dalsi
> pozadavek spusteni.

Jenze pokud vykonavas cely ten kod tak, ze jej cely volas prostrednictvim
metody TThread.Synchornize, tak nema smysl aby tam ten thread byl. Tim to
volani totiz stejne provedes v kontextu hlavniho threadu.

Petr Vones


Odpovedá: Slavomir Skopalik

1. 10. 2004 17:10


> Vlakno:=TThread(nil); //tady mi vypadlo ".Create"
> Vlakno.Params.Clear; //<-- tady se to kousne beze slova...
> aplikace se tvari, ze v pohode bezi...  
>
> atd. Pak se mi nekde stane, ze mi nejaka cast kodu toho
> "Proved" zhuci na vyjimku - bohuzel "zatim" nepisu kod bez
> chyb. Proto jsem to dal do toho bloku try->finally a doufal,
> ze kdyz mi to v tom kodu zhuci, dostane se to do bloku
> finally a aplikace zahlasi chybu, ke ktere doslo, a bude dal
> pokracovat...

Aplikace zadnou chybu nezahlasi, ta je "preposlana" prislusnemu threadu
a tam ti chybi jeji obslouzeni.


>
> bohuzel se tak nedeje. V kodu pouzivam komponenty
> TIBDatabase, TIBTransaction, TIBDataset, TIBQuery - nekde
> jsem vycetl, ze IB/FB neni tzv. "thread safety" a tak si
> vsechny spojeni na databazi vytvarim v tele Create toho
> threadu. Doufam, ze to s tim nesouvisi...

Tak jak je to napsane, klidne muzes thready smazat,
aplikace bude fungovat o neco (tisicin promile) tychleji.

 Slavek


Odpovedá: Petr Fejfar

1. 10. 2004 17:47

Martin Krim wrote:

> a za pokus by stalo zkusit
> implementovat obsluhu udalosti TApplication.OnException

Tak to ne - synchronizovana metoda se spousti ve funkci
CheckSynchronization()
a pripadna vyjimka je zachycena pomoci try-expect a jeji instance prirazena
do property
TThread.SynchronizeException.

pf



Odpovedá: Slavomir Skopalik

1. 10. 2004 20:29

>
> IMHO, kazde vlakno ma svuj vlastni zasobnik a vyjimky se vzdy
> siri po zasobniku, tedy volanim metody Synchronize
> presmerujete vykonani metody Proved do hlavniho vlakna
> programu, tedy k vyvolani vyjimky by melo dojit v hlavnim

Jenze je to trochu jinak, doporucuji se podivat do kodu
funkce CheckSynchronize(Timeout: Integer = 0): Boolean;

specialne na tuto cast:
try
              SyncProc.SyncRec.FMethod;
            except
              SyncProc.SyncRec.FSynchronizeException :=
AcquireExceptionObject;
            end;

Zde je jasne videt, ze pripadna vyjimka bude zachycena a ulozena !

Pak nasleduje jiz v kontextu prislusneho vlakna tento kod:

    if Assigned(ASyncRec.FSynchronizeException) then raise
ASyncRec.FSynchronizeException;

Tim ovsem dojde ke zniceni zasobniku (pokud pouzivate JCL)  , ale
vyjimka je hozena ve vlakna  .

 Slavek

> vlakne programu a za pokus by stalo zkusit implementovat
> obsluhu udalosti TApplication.OnException a pokusit se tak
> zachytit vyjimku - BTW, pomoci teto udalosti muzete
> zachytavat vsechny neosetrene vyjimky (z hlavniho vlakna
> programu) a vypsat uzivateli neco jako
"Omlouvame se za
> zpusobene potize......".